import static org.junit.Assert.*;

import org.junit.*;

import edu.gatech.oad.mule.MULE;
import edu.gatech.oad.mule.Player;
import edu.gatech.oad.mule.Tile;
import edu.gatech.oad.mule.model.GameStateMachine.GameState;

/**
 * This class performs some JUnit testing on the 
 * interact() method inside of the Tile class
 * 
 * @author Brendan McGarry
 * @version %I%, %G%
 */
public class TileInteractTests {

	//the tile
	private Tile t;
	//(x,y) location and the type of tile
	private int x = 0;
	private int y = 0;
	private char type = Tile.RIVER;
	
	//the player object
	private Player p;
	
	//MULE object
	private MULE m;
	
	@Before
	public void setUp(){
		t = new Tile(x, y, type);
		p = new Player();
		m = new MULE();
	}//end method setUp
	
	//====================
	//  Land Grant Phase Testing
	//====================
	
	/*
	 * This test ensures that the player is starting off with
	 * no tiles
	 */
	@Test
	public void testInitialTileCount() {
		assertEquals(0, p.getNumOwnedTiles());
	}//end method testInitialTileCount
	
	/*
	 * This test ensures that a player does not acquire a tile
	 * if he/she does not have enough money to buy it
	 */
	@Test
	public void testInsufficientFunds(){
		p.addMoney(-5000);
		t.interact(p, GameState.LAND_GRANT, 2, 1500);
		assertEquals(0, p.getNumOwnedTiles());
	}//end method testInsufficientFunds
	
	/*
	 * This test ensures that if it is the first or second
	 * round of the game in the land grant phase, then the
	 * player will receive the plot for free.
	 */
	@Test
	public void testRound0FreeLand() {
		t.interact(p, GameState.LAND_GRANT, 0, 1500);
		assertEquals(1000, p.getMoney());
	}//end method testRound0FreeLand
	
	/*
	 * This test ensures that if it is the first or second
	 * round of the game in the land grant phase, then the
	 * player will receive the plot for free.
	 */
	@Test
	public void testRound1FreeLand() {
		t.interact(p, GameState.LAND_GRANT, 1, 1500);
		assertEquals(1000, p.getMoney());
	}//end method testRound1FreeLand
	
	/*
	 * This test ensures that player's are being charged for
	 * land after the first and second round
	 */
	@Test
	public void testRound2LandCost() {
		t.interact(p, GameState.LAND_GRANT, 2, 1500);
		assertEquals(700, p.getMoney());
	}//end method testRound2LandCost
	
	/*
	 * This test ensures that the player's tile count is being
	 * incremented after getting a plot of land
	 */
	@Test
	public void testTileCount() {
		t.interact(p, GameState.LAND_GRANT, 0, 1500);
		assertEquals(1, p.getNumOwnedTiles());
	}//end method testInitialTileCount
	
	/*
	 * This test ensures that when a player acquires a plot of
	 * land the tile's owner is set to that player
	 */
	@Test
	public void testTileOwner(){
		t.interact(p, GameState.LAND_GRANT, 0, 1500);
		assertTrue(t.getOwner().equals(p));
	}//end method testTileOwner
	
	//====================
	//  Development Phase Testing
	//====================
	
	/*
	 * This test ensures that if a player owns a tile and outfits a
	 * MULE, the player can then place that MULE on the tile he/she
	 * owns. 
	 * 
	 * The player should no longer have a MULE
	 */
	@Test
	public void testMULEDeployedPlayer(){
		m.outfit(MULE.ENERGY);
		p.setMULE(m);
		t.interact(p, GameState.LAND_GRANT, 0, 1500);
		t.interact(p, GameState.DEVELOPMENT, 0, 1500);
		assertEquals(null, p.getMULE());
	}//end method testMULEDeployedTile
	
	/*
	 * This test ensures that if a player owns a tile and outfits a
	 * MULE, the player can then place that MULE on the tile he/she
	 * owns. 
	 * 
	 * The tile should have the Player's mule
	 */
	@Test
	public void testMULEDeployedTile(){
		m.outfit(MULE.ENERGY);
		p.setMULE(m);
		t.interact(p, GameState.LAND_GRANT, 0, 1500);
		t.interact(p, GameState.DEVELOPMENT, 0, 1500);
		assertTrue(t.hasMULE());
	}//end method testMULEDeployedTile
	
	/*
	 * This test ensures that if a player owns a tile with an
	 * outfitted MULE on it, he/she can remove the MULE from
	 * the tile and place it back into the inventory
	 * 
	 * In this test, the tile has a MULE and the player
	 * has a free space to hold the MULE
	 */
	@Test
	public void testMULERemovedPlayer1(){
		m.outfit(MULE.ENERGY);
		p.setMULE(m);
		t.interact(p, GameState.LAND_GRANT, 0, 1500);
		t.interact(p, GameState.DEVELOPMENT, 0, 1500);
		t.interact(p, GameState.DEVELOPMENT, 0, 1500);
		assertEquals(m, p.getMULE());
	}//end method testMULERemovedPlayer1
	
	/*
	 * This test ensures that if a player owns a tile with an
	 * outfitted MULE on it, he/she can remove the MULE from
	 * the tile and place it back into the inventory
	 * 
	 * In this test, the tile has a MULE and the player
	 * does not have a free space to hold the MULE
	 */
	@Test
	public void testMULERemovedPlayer2(){
		m.outfit(MULE.ENERGY);
		p.setMULE(m);
		t.interact(p, GameState.LAND_GRANT, 0, 1500);
		t.interact(p, GameState.DEVELOPMENT, 0, 1500);
		MULE m2 = new MULE();
		m2.outfit(MULE.SMITHORE);
		p.setMULE(m2);
		t.interact(p, GameState.DEVELOPMENT, 0, 1500);
		assertEquals(m2, p.getMULE());
	}//end method testMULERemovedPlayer2
	
	/*
	 * This test ensures that if a player owns a tile with an
	 * outfitted MULE on it, he/she can remove the MULE from
	 * the tile and place it back into the inventory
	 * 
	 * In this test, the tile has a MULE and the player
	 * has a free space to hold the MULE
	 */
	@Test
	public void testMULERemovedTile(){
		m.outfit(MULE.ENERGY);
		p.setMULE(m);
		t.interact(p, GameState.LAND_GRANT, 0, 1500);
		t.interact(p, GameState.DEVELOPMENT, 0, 1500);
		t.interact(p, GameState.DEVELOPMENT, 0, 1500);
		assertFalse(t.hasMULE());
	}//end method testMULERemovedTile
	
	/*
	 * This test checks that if a player attempts to place
	 * a MULE on a tile he/she does not own, the MULE escapes.
	 * 
	 * The player should have no MULE in his/her inventory
	 */
	@Test
	public void testRunawayMULEPlayer(){
		m.outfit(MULE.ENERGY);
		p.setMULE(m);
		t.interact(p, GameState.DEVELOPMENT, 0, 1500);
		assertTrue(p.getMULE() == null);
	}//end method testRunawayMULEPlayer
	
	/*
	 * This test checks that if a player attempts to place
	 * a MULE on a tile he/she does not own, the MULE escapes.
	 * 
	 * The tile should not have a mule on it.
	 */
	@Test
	public void testRunawayMULETile(){
		m.outfit(MULE.ENERGY);
		p.setMULE(m);
		t.interact(p, GameState.DEVELOPMENT, 0, 1500);
		assertFalse(t.hasMULE());
	}//end method testRunawayMULEPlayer

}//end class TileInteractTests
